package org.dromara.netbar.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.dromara.common.core.constant.NetbarConstants;
import org.dromara.common.core.enums.FormatsType;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.RedisKeyGeneratorUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.netbar.domain.vo.NetbarCouponVo;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.dromara.netbar.domain.bo.NetbarCouponMemberBo;
import org.dromara.netbar.domain.vo.NetbarCouponMemberVo;
import org.dromara.netbar.domain.NetbarCouponMember;
import org.dromara.netbar.mapper.NetbarCouponMemberMapper;
import org.dromara.netbar.service.INetbarCouponMemberService;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 会员-卡券关联Service业务层处理
 *
 * @author Lion Li
 * @date 2025-07-15
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class NetbarCouponMemberServiceImpl implements INetbarCouponMemberService {

    private final NetbarCouponMemberMapper baseMapper;

    /**
     * 查询会员-卡券关联
     *
     * @param couponMemberId 主键
     * @return 会员-卡券关联
     */
    @Override
    public NetbarCouponMemberVo queryById(Long couponMemberId){
        return baseMapper.selectVoById(couponMemberId);
    }

    /**
     * 分页查询会员-卡券关联列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 会员-卡券关联分页列表
     */
    @Override
    public TableDataInfo<NetbarCouponMemberVo> queryPageList(NetbarCouponMemberBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<NetbarCouponMember> lqw = buildQueryWrapper(bo);
        Page<NetbarCouponMemberVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的会员-卡券关联列表
     *
     * @param bo 查询条件
     * @return 会员-卡券关联列表
     */
    @Override
    public List<NetbarCouponMemberVo> queryList(NetbarCouponMemberBo bo) {
        LambdaQueryWrapper<NetbarCouponMember> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<NetbarCouponMember> buildQueryWrapper(NetbarCouponMemberBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<NetbarCouponMember> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(NetbarCouponMember::getCouponMemberId);
        lqw.eq(bo.getCouponId() != null, NetbarCouponMember::getCouponId, bo.getCouponId());
        lqw.eq(bo.getMemberId() != null, NetbarCouponMember::getMemberId, bo.getMemberId());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), NetbarCouponMember::getStatus, bo.getStatus());
        lqw.eq(bo.getUseTime() != null, NetbarCouponMember::getUseTime, bo.getUseTime());
        return lqw;
    }

    /**
     * 新增会员-卡券关联
     *
     * @param bo 会员-卡券关联
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(NetbarCouponMemberBo bo) {
        NetbarCouponMember add = MapstructUtils.convert(bo, NetbarCouponMember.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setCouponMemberId(add.getCouponMemberId());
        }
        return flag;
    }

    /**
     * 修改会员-卡券关联
     *
     * @param bo 会员-卡券关联
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(NetbarCouponMemberBo bo) {
        NetbarCouponMember update = MapstructUtils.convert(bo, NetbarCouponMember.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(NetbarCouponMember entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除会员-卡券关联信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    @Override
    public List<NetbarCouponMemberVo> listCouponMemberByMemberIds(List<Long> memberIds) {
        return baseMapper.selectCouponMemberByMemberIds(memberIds);
    }

    @Override
    public Map<String, NetbarCouponVo> listCouponMemberUsed(String tenantId, List<Long> memberIds) {
        Map<String, NetbarCouponVo> cacheMap = RedisUtils.getCacheMap(RedisKeyGeneratorUtils.getMemberUseCouponKey(tenantId));
        if (null == cacheMap || cacheMap.isEmpty()) {
            return Collections.emptyMap();
        }
        return cacheMap;
    }

    @Override
    public List<NetbarCouponMemberVo> listCouponMemberGroupByMemberIds(List<Long> memberIds, String nowDateStr) {
        return baseMapper.selectCouponMemberGroupByMemberIds(memberIds, nowDateStr);
    }

    @Override
    public List<NetbarCouponMemberVo> listCouponMemberGroupByMemberIds(List<Long> memberIds) {
        return listCouponMemberGroupByMemberIds(memberIds, DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_HH_MM_SS, new Date()));
    }

    @Override
    public Map<String, Map<String, Object>> getBatchMemberUseCouponMapByTenantId(String tenantId) {
        if (null == tenantId) {
            return Collections.emptyMap();
        }
        return RedisUtils.getCacheMap(RedisKeyGeneratorUtils.getMemberUseCouponKey(tenantId));
    }

    @Override
    public Map<String, Map<String, Object>> getMemberUserCouponMapByTenantIdAndMemberId(String tenantId, Long memberId) {
        if (null == tenantId || null == memberId){
            return Collections.emptyMap();
        }
        // 批量获取
        return RedisUtils.getMultiCacheMapValue(RedisKeyGeneratorUtils.getMemberUseCouponKey(tenantId), RedisKeyGeneratorUtils.getMemberUseCouponHKeys(memberId));
    }

    @Override
    public Map<String, Object> getMemberUserCouponMapByTenantIdAndMemberIdAndCouponType(String tenantId, Long memberId, String couponType) {
        if (null == tenantId || null == memberId || null == couponType){
            return Collections.emptyMap();
        }
        return RedisUtils.getCacheMapValue(RedisKeyGeneratorUtils.getMemberUseCouponKey(tenantId),RedisKeyGeneratorUtils.getMemberUseCouponHKey(memberId, couponType));
    }

    @Override
    public void saveCouponMemberByMap(Map<Long, Long> couponNumberMap, List<Long> memberIdList) {
        // 1. 参数校验（防御式编程）
        // - 检查couponNumberMap是否为null或空
        // - 检查memberIdList是否为null或空
        if (null == couponNumberMap || couponNumberMap.isEmpty() || CollectionUtil.isEmpty(memberIdList)) {
            log.warn("参数校验失败：couponNumberMap或memberIdList为空");
            return;
        }
        List<NetbarCouponMember> bos = getNetbarCouponMembers(couponNumberMap, memberIdList);
        if (CollectionUtil.isNotEmpty(bos)) {
            // 5. 执行数据库插入
            baseMapper.insertBatch(bos);
            // 6. 日志记录（可选）
            log.info("卡券发放完成，共为{}个会员发放{}种卡券",
                memberIdList.size(),
                couponNumberMap.size());
        }
    }

    @Override
    public List<NetbarCouponMemberVo> listCouponMemberAuto(List<Long> memberIds, String couponType) {
        if(CollectionUtil.isEmpty(memberIds)){
            return Collections.emptyList();
        }
        String date_format = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        List<NetbarCouponMemberVo> couponMemberVoList = baseMapper.selectCouponMemberGroupByMemberIds(memberIds, date_format);
        if (CollectionUtil.isEmpty(couponMemberVoList)) {
            return Collections.emptyList();
        }
        return couponMemberVoList.stream().filter(item -> null != item.getCoupon() && couponType.equals(item.getCoupon().getCouponType())).toList();
    }

    @Override
    public Map<Long, Integer> countMapByCouponIds(Long[] couponIds) {
        return baseMapper.countMapByCouponIds(couponIds);
    }

    @Override
    public void changeStatusByMemberIdListByCouponIdList(List<Long> memberIdList, List<Long> couponIdList, String status) {
        if(memberIdList.isEmpty() || couponIdList.isEmpty() || status.isEmpty()) return;
        LambdaUpdateWrapper<NetbarCouponMember> luw = new LambdaUpdateWrapper<>();
        luw.in(NetbarCouponMember::getCouponId, couponIdList);
        luw.in(NetbarCouponMember::getMemberId, memberIdList);
        luw.set(NetbarCouponMember::getStatus, status);
        luw.set(NetbarCouponMember::getUseTime, new Date());
        baseMapper.update(luw);
    }

    @Override
    public void deleteCouponMember(NetbarCouponMemberBo bo) {
        List<Long> memberIds = bo.getMemberIds();
        Long couponId = bo.getCouponId();
        long couponCount = bo.getCouponCount();
        LambdaQueryWrapper<NetbarCouponMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(NetbarCouponMember::getCouponId, couponId);
        wrapper.in(NetbarCouponMember::getMemberId, memberIds);
        wrapper.eq(NetbarCouponMember::getStatus, "0");
        List<NetbarCouponMemberVo> couponMemberVoList = baseMapper.selectVoList(wrapper);
        List<Long> removeIds = new ArrayList<>();
        for (int i = 0; i < couponMemberVoList.size(); i++) {
            if((i+1) > couponCount) break;
            removeIds.add(couponMemberVoList.get(i).getCouponMemberId());
        }
        if(CollectionUtil.isNotEmpty(removeIds)){
            baseMapper.deleteByIds(removeIds);
        }
    }

    @Override
    public List<NetbarCouponMemberVo> queryDjqListByBalance(Long memberId, Long balance) {
        return baseMapper.selectDjqListByBalance(memberId, balance,NetbarConstants.Coupon.TYPE_6, DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_HH_MM_SS, new Date()));
    }

    @Override
    public List<NetbarCouponMemberVo> listCouponMemberByCouponMemberIds(List<Long> useCouponMemberIds, String couponType) {
        return baseMapper.selectListCouponMemberByCouponMemberIds(useCouponMemberIds, couponType, DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_HH_MM_SS, new Date()));
    }

    @NotNull
    private static List<NetbarCouponMember> getNetbarCouponMembers(Map<Long, Long> couponNumberMap, List<Long> memberIdList) {
        List<NetbarCouponMember> bos = new ArrayList<>();
        NetbarCouponMember bo;
        // 2. 遍历会员ID列表
        // - 每个会员都需要发放所有类型的卡券
        long couponId = 0;
        long couponCount = 0;
        for (Long memberId : memberIdList) {
            // 3. 遍历卡券类型及对应数量
            // - entrySet()比keySet()更高效（避免二次get操作）
            for (Map.Entry<Long, Long> entry : couponNumberMap.entrySet()) {
                couponId = entry.getKey();
                couponCount = entry.getValue();
                for (int i = 0; i < couponCount; i++) {
                    // 4. 构建卡券发放业务对象
                    bo = new NetbarCouponMember();
                    bo.setCouponId(couponId);
                    bo.setMemberId(memberId);
                    bos.add(bo);
                }
            }
        }
        return bos;
    }


}
